import * as THREE from "three";

export class DefineControl {
  scene: any;
  camera: any;
  player: any;
  cameraGroup: any;
  v: any = new THREE.Vector3(0, 0, 0); //速度和方向
  vMax: number = 5; //最大速度
  a: number = 12; //加速度
  t: number = 0; //时间
  pos0: any; //初始位置
  damping: any = -0.04; //阻力，v乘以一个小于1的数值，重复多次就会逼近0
  keyStates = {
    W: false,
    A: false,
    S: false,
    D: false,
  }; //控制键
  constructor(scene: any, camera: any) {
    this.scene = scene;
    this.camera = camera;

    this.addkeyBoard();
    this.addMouse();
    this.initPlayer();
    this.initCamera();
  }
  initPlayer() {
    this.player = new THREE.Mesh(
      new THREE.SphereGeometry(0.3),
      // new THREE.BoxGeometry( 2, 1.5, 0.1 ),
      new THREE.MeshBasicMaterial({
        color: 0x00ffff,
        // transparent: true,
        // opacity: 0,
      })
    );
    this.player.position.set(0, 16.5, 0); //在scene中为世界坐标
    this.pos0 = this.player.position.clone();
    this.scene.add(this.player);
  }
  initCamera() {
    this.cameraGroup = new THREE.Group();
    this.cameraGroup.add(this.camera);
    this.cameraGroup.position.set(0, 0, 0);
    this.player.add(this.cameraGroup); //相机作为cameraGroup子对象
    this.camera.position.set(0, 3, 1); //本地坐标
    const temp = new THREE.Vector3();
    this.camera.getWorldPosition(temp);
    let cameraHelper = new THREE.Mesh(
      new THREE.SphereGeometry(0.3),
      new THREE.MeshBasicMaterial({ color: 0x00ff00 })
    );
    cameraHelper.position.copy(temp);
    this.scene.add(cameraHelper);
  }
  update(delta) {
    this.t = delta;
    // if (this.keyStates.W) {
    //   // 在t时间内，以速度v运动的位移量
    //   this.t += delta;
    //   const dis = this.v.clone().multiplyScalar(this.t);
    //   // player初始位置加上t时间段内运动的位移量
    //   const newPos = this.pos0.clone().add(dis);
    //   this.player.position.copy(newPos);
    // }
    if (this.v.length() < this.vMax) {
      //限速
      if (this.keyStates.W) {
        //z轴正方向：(0, 0, 1)，z轴反方向(0, 0, -1)，x轴正方向：(1, 0, )，x轴反方向：(-1, 0, 0)
        const front = new THREE.Vector3();
        this.player.getWorldDirection(front); //获取玩家角色(相机)正前方
        if (!this.rayCheckBump(front.multiplyScalar(-1))) return;
        // 键按下时候，速度随着时间增加
        this.v.add(front.multiplyScalar(this.a * this.t));
      } else if (this.keyStates.A) {
        const front = new THREE.Vector3();
        this.player.getWorldDirection(front);
        const up = new THREE.Vector3(0, 1, 0); //y方向
        const left = up.clone().cross(front);
        if (!this.rayCheckBump(left.multiplyScalar(-1))) return;
        this.v.add(left.multiplyScalar(this.a * this.t));
      } else if (this.keyStates.S) {
        const front = new THREE.Vector3();
        this.player.getWorldDirection(front);
        if (!this.rayCheckBump(front.multiplyScalar(-1))) return;
        this.v.add(front.multiplyScalar(-this.a * this.t));
      } else if (this.keyStates.D) {
        // this.player.rotateY(-Math.PI / 2)//旋转90度
        const front = new THREE.Vector3();
        this.player.getWorldDirection(front);
        const up = new THREE.Vector3(0, 1, 0);
        const right = front.clone().cross(up);
        if (!this.rayCheckBump(right.multiplyScalar(-1))) return;
        this.v.add(right.multiplyScalar(this.a * this.t));
      }
    }
    this.v.addScaledVector(this.v, this.damping); //阻尼减速
    // 在间隔deltaTime时间内，玩家角色位移变化计算(速度*时间)
    const deltaPos = this.v.clone().multiplyScalar(this.t);
    this.player.position.add(deltaPos); //更新玩家角色的位置
  }
  addkeyBoard() {
    document.onkeydown = (e: any) => {
      this.keyBoardEvent(e, "down");
    };
    document.onkeyup = (e: any) => {
      this.keyBoardEvent(e, "up");
    };
  }
  keyBoardEvent(e, type) {
    if (e.keyCode == 27) {
      //esc
      document.exitPointerLock();
      return;
    }
    switch (e.keyCode) {
      case 38: // up
      case 87: // w
        if (type == "down") {
          this.keyStates.W = true;
        } else {
          this.keyStates.W = false;
        }
        break;
      case 37: // left
      case 65: // a
        if (type == "down") {
          this.keyStates.A = true;
        } else {
          this.keyStates.A = false;
        }
        break;
      case 40: // down
      case 83: // s
        if (type == "down") {
          this.keyStates.S = true;
        } else {
          this.keyStates.S = false;
        }
        break;
      case 39: // right
      case 68: // d
        if (type == "down") {
          this.keyStates.D = true;
        } else {
          this.keyStates.D = false;
        }
        break;
    }
  }
  addMouse() {
    let leftButtonBool = false; //记录鼠标左键状态
    // 上下俯仰角度范围
    const angleMin = THREE.MathUtils.degToRad(40); //角度转弧度
    const angleMax = THREE.MathUtils.degToRad(90);
    document.addEventListener("mousedown", (event) => {
      leftButtonBool = true;
      //   document.body.requestPointerLock(); //body页面指针锁定,当鼠标左键按下后进入指针锁定模式(鼠标无限滑动)
    });
    document.addEventListener("mousemove", (event) => {
      // 注意rotation.y += 与 -= 区别，左右旋转时候方向相反
      //event.movementX缩小一定倍数改变旋转控制的灵敏度
      if (leftButtonBool) {
        this.player.rotation.y -= event.movementX / 600; //左右
        //cameraGroup鼠标上下移动只改变相机视角，不改变player角度
        this.cameraGroup.rotation.x -= event.movementY / 600; //俯仰

        // 一旦判断.rotation.x小于-15，就设置为-15，大于15，就设置为15
        if (this.cameraGroup.rotation.x < angleMin) {
          this.cameraGroup.rotation.x = angleMin;
        }
        if (this.cameraGroup.rotation.x > angleMax) {
          this.cameraGroup.rotation.x = angleMax;
        }
      }
      if (document.pointerLockElement == document.body) {
        // 指针锁定模式下，才能执行的代码
        this.player.rotation.y -= event.movementX / 600; //左右
        this.cameraGroup.rotation.x -= event.movementY / 600; //俯仰
        // 一旦判断.rotation.x小于-15，就设置为-15，大于15，就设置为15
        if (this.cameraGroup.rotation.x < angleMin) {
          this.cameraGroup.rotation.x = angleMin;
        }
        if (this.cameraGroup.rotation.x > angleMax) {
          this.cameraGroup.rotation.x = angleMax;
        }
      }
    });
    document.addEventListener("mouseup", () => {
      leftButtonBool = false;
    });
  }
  rayCheckBump(direction) {
    // 创建一个射线投射器
    const origin = new THREE.Vector3();
    this.cameraGroup.getWorldPosition(origin);
    const raycaster = new THREE.Raycaster(origin, direction);
    const intersects = raycaster.intersectObjects(this.scene.children);
    //distance:相机和射线交叉点的最短距离同intersects[0].point.sub(this.camera.position)
    console.log("距离", intersects[0]?.distance, intersects[0]?.object.name);
    if (intersects[0]?.distance < 1 && intersects[0]?.object.name) {
      intersects[0].object.material.color.set(0xff0000);
      return false;
    } else {
      return true;
    }
  }
}
